package com.qfx.demo.util;

import java.security.Key;
import java.util.Date;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;

public class ToolToken {

	/**
	 * 签名秘钥
	 * 可以换成 秘钥 注入,长度最好不要小于50,否则可能会报"The signing key's size is 24 bits which is not secure enough for the HS256 a"的异常
	 */
	public static final String SECRET = "jnxj_blh";
	/**
	 * 签发地
	 */
	public static final String ISSUER = "jnxj";
	/**
	 * 有效期(秒)
	 */
//	public static final long TTL_MILLIS = 3600 * 24 * 30;
	public static final long TTL_MILLIS = -1;	// 默认永久有效

	/**
	 * 生成token
	 *
	 * @param id 一般传入userName
	 * @param subject 该JWT所面向的用户
	 * @return
	 */
	public static String createJwtToken(String id, String subject) {
		return createJwtToken(id, ISSUER, subject, TTL_MILLIS);
	}

	public static String createJwtToken(String id) {
		return createJwtToken(id, ISSUER, "", TTL_MILLIS);
	}

	/**
	 * 生成Token
	 *
	 * @param id        编号
	 * @param issuer    该JWT的签发者，是否使用是可选的
	 * @param subject   该JWT所面向的用户，是否使用是可选的；
	 * @param ttlMillis 有效时间(秒,过期会报错)
	 * @return token String
	 */
	public static String createJwtToken(String id, String issuer, String subject, long ttlMillis) {

		// 签名算法 ，将对token进行签名
		SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

		// 生成签发时间
		long nowMillis = System.currentTimeMillis();
//		Date now = new Date(nowMillis);

		// 通过秘钥签名JWT
		byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET);
		Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

		// 让我们设置JWT声明
		JwtBuilder builder = Jwts.builder().setId(id)
//				.setIssuedAt(now)	//暂不开放签发时间
				.setSubject(subject).setIssuer(issuer)
				.signWith(signatureAlgorithm, signingKey);

		// 如果指定了有效期,那么让我们添加过期时间
		if (ttlMillis >= 0) {
			long expMillis = nowMillis + ttlMillis * 1000;
			Date exp = new Date(expMillis);
			builder.setExpiration(exp);
			
			System.out.println("JWT有效期至:" + ToolDate.dateTimeToString(exp));
		}

		// 构建JWT并将其序列化为一个紧凑的url安全字符串
		return builder.compact();

	}

	/**
	 * Token解析方法
	 * 
	 * @param jwt Token
	 * @return
	 */
	public static Claims parseJWT(String jwt) {
		Claims claims = null;
		// 如果这行代码不是签名的JWS(如预期)，那么它将抛出异常
		try {
			claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(SECRET)).parseClaimsJws(jwt).getBody();
			String issuer 	= claims.getIssuer();
			if (!ISSUER.equals(issuer)) {
				claims = null;
				System.out.println("JWT的签发地不在范围内");
			}
		} catch(ExpiredJwtException e) {
			System.out.println("JWT 已过期!");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return claims;
	}
	
    /**
     * 验证是否通过
     * @param jwt
     * @return
     */
    public static boolean validateToken(String jwt) {
        try {
        	Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(SECRET)).parseClaimsJws(jwt).getBody();
            return true;
        } catch (SignatureException ex) {
            System.out.println("Invalid JWT signature");
        } catch (MalformedJwtException ex) {
            System.out.println("Invalid JWT token");
        } catch (ExpiredJwtException ex) {
            System.out.println("Expired JWT token");
        } catch (UnsupportedJwtException ex) {
            System.out.println("Unsupported JWT token");
        } catch (IllegalArgumentException ex) {
            System.out.println("JWT claims string is empty.");
        }
        return false;
    }
	
	
	public static void main(String[] args) {
//		String token = ToolToken.createJwtToken("1001001");
		String token = ToolToken.createJwtToken("zhangsan","zhangsan");
		System.out.println(token);
		Claims claims = ToolToken.parseJWT(token);
		System.out.println("--1" + claims.getSubject());
		System.out.println("--2" + claims);
//		System.out.println("------------------");
//		String token2 = ToolToken.createJwtToken("我去啊", "ltz");
//		System.out.println(token2);
//		Claims claims2 = ToolToken.parseJWT(token2);
//		System.out.println(claims2);
//		System.out.println(claims2.get("jti"));
//		System.out.println("------------------");
//		String token3 = ToolToken.createJwtToken("zhangsan", "jnxj111", "app22", TTL_MILLIS);
//		System.out.println(token3);
//		Claims claims3 = ToolToken.parseJWT(token3);
//		System.out.println(claims3);
//		System.out.println(claims3.getId());
	}
}
